print-job-board - #5
Conversation
…nhance print job model with new fields
|
Warning Review limit reached
Next review available in: 5 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (15)
WalkthroughDie Anwendung erhält ein statusbasiertes Print Board mit Job-Codes, Dateianhängen, Filamentverwaltung und STL-/3MF-Vorschau. Datenbankmodell, Migrationen, Upload-Speicher, API, Einstellungen, Seed-Daten und Navigation wurden angepasst. ChangesDatenmodell und Persistenz
Print-Job-Workflow
STL-/3MF-Viewer
Board, Formulare und Navigation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant Mitarbeiter
participant PrintBoard
participant PrintsRoute
participant Database
participant Inventory
Mitarbeiter->>PrintBoard: Print Job anlegen
PrintBoard->>PrintsRoute: Formular mit Filament und Dateien senden
PrintsRoute->>Database: Print Job als planned speichern
Mitarbeiter->>PrintBoard: Status auf done setzen
PrintBoard->>PrintsRoute: Statuswechsel senden
PrintsRoute->>Inventory: Filamentverbrauch abziehen
Inventory-->>PrintsRoute: Bestand aktualisieren
PrintsRoute->>Database: completed_at speichern
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…pulate print jobs with various statuses and details
There was a problem hiding this comment.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
seed.py (1)
130-147: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winDateilöschung nach dem Commit ausführen.
clear_tableslöscht die hochgeladenen Dateien vom Datenträger (Zeile 135-136), bevor die zugehörigen DB-Zeilen gelöscht und committet werden (Zeile 145-146). Schlägt eines derdelete(model)-Statements fehl, rollt die Transaktion zurück, aber die bereits gelöschten Dateien bleiben verloren. Dadurch verweisen verbleibendePrintJobFile-Zeilen auf nicht mehr existierende Dateien.Verschieben Sie die Dateilöschung hinter
session.commit().🔧 Vorgeschlagene Reihenfolge-Korrektur
demo_uploads = (await session.execute( select(PrintJobFile.stored_filename).where(PrintJobFile.stored_filename.is_not(None)) )).scalars().all() - for stored_filename in demo_uploads: - (Path(Config.UPLOAD_DIR) / stored_filename).unlink(missing_ok=True) - for model in ( PrintJobFile, PrintJobLine, PrintJob, PriceAlertEvent, PriceSnapshot, ShopLink, Spool, PurchaseLine, Purchase, FilamentProduct, Manufacturer, ShopRule, ): await session.execute(delete(model)) await session.commit() + for stored_filename in demo_uploads: + (Path(Config.UPLOAD_DIR) / stored_filename).unlink(missing_ok=True) print("clear_tables: all demo tables truncated.")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@seed.py` around lines 130 - 147, Verschiebe die Dateilöschung in clear_tables hinter await session.commit(), sodass die Upload-Dateien erst nach erfolgreicher Löschung der Datenbankzeilen entfernt werden. Behalte das vorherige Sammeln der stored_filename-Werte bei und führe die bestehende Path.unlink-Logik anschließend aus.
🧹 Nitpick comments (5)
app/static/js/vendor/three/addons/loaders/3MFLoader.js (1)
1095-1126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLint-Fehler stammen aus unverändertem Vendor-Code.
Biome meldet
noSwitchDeclarationsin diesemswitch-Block. Der Code ist eine unveränderte three.js-Kopie. Ändern Sie ihn nicht. Schließen Sie stattdessenapp/static/js/vendor/**in der Biome-Konfiguration aus. Dieselbe Meldung tritt inapp/static/js/vendor/three/addons/controls/OrbitControls.jsauf.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/static/js/vendor/three/addons/loaders/3MFLoader.js` around lines 1095 - 1126, Exclude app/static/js/vendor/** from the Biome lint configuration so vendor code is not checked for noSwitchDeclarations. Do not modify the switch in the 3MFLoader resource handling or the corresponding OrbitControls.js code.Source: Linters/SAST tools
app/static/js/vendor/three/addons/controls/OrbitControls.js (1)
1-12: 🩺 Stability & Availability | 🔵 TrivialVendor-Versionierung für
three.jsdokumentieren.Diese Vendor-Dateien beziehen sich auf
REVISION = '169';Controlsist daher inthree.module.jsvorhanden. Dokumentieren Sie, dass alle Dateien inapp/static/js/vendor/threeaufthree.js r169basieren, damit spätere Updates konsistent bleiben.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/static/js/vendor/three/addons/controls/OrbitControls.js` around lines 1 - 12, Document in the vendor area that all files under app/static/js/vendor/three are based on three.js r169, including that the imported Controls symbol is available in that revision. Add the note in the established vendor documentation or an appropriate adjacent comment without changing the import behavior.app/templates/prints/index.html (1)
159-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTastaturbedienung für das Modal ergänzen.
Das Modal lässt sich nur über die Schaltfläche schließen. Es gibt keinen
Escape-Handler und kein Fokus-Management. Ergänzen Sierole="dialog"undaria-modal="true", setzen Sie den Fokus beim Öffnen auf die Schließen-Schaltfläche und schließen Sie das Modal beiEscape.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/templates/prints/index.html` around lines 159 - 171, Update the viewer modal container with role="dialog" and aria-modal="true"; in the existing open/close viewer flow, focus the close button after opening and handle Escape to invoke closeViewer(). Ensure the close button has a stable selector or identifier for focus management.app/routes/prints.py (2)
150-165: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueKonstanten vor ihre Nutzung im Modul stellen.
_ALLOWED_FILE_EXTENSIONS,_MAX_UPLOAD_MB,_KNOWN_PROVIDERSund_FILE_MIMETYPESstehen direkt hinter dem Funktionskörper von_viewer_js_versionund nach den Funktionen, die sie verwenden. Das ist zur Laufzeit korrekt, erschwert aber das Lesen. Verschieben Sie die Konstanten zum Modulkopf neben_DONE_COLUMN_LIMIT.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/routes/prints.py` around lines 150 - 165, Verschieben Sie die Konstanten _ALLOWED_FILE_EXTENSIONS, _MAX_UPLOAD_MB, _KNOWN_PROVIDERS und _FILE_MIMETYPES im Modul an den Kopfbereich neben _DONE_COLUMN_LIMIT, sodass sie vor den Funktionen definiert sind, die sie verwenden; ändern Sie ihre Werte nicht.
222-235: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAbgeschlossene Aufträge in der Datenbank begrenzen.
Die Abfrage lädt alle Druckaufträge samt Zeilen und Dateien. Die Filterung nach Status und das Limit
_DONE_COLUMN_LIMITerfolgen erst im Speicher. Mit wachsender Historie steigt die Ladezeit unbegrenzt. Führen Sie getrennte Abfragen pro Status aus und begrenzen Sie die Spalte „Fertig“ perORDER BYundLIMIT.totalkönnen Sie überfunc.countermitteln.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/routes/prints.py` around lines 222 - 235, Ersetze die gemeinsame Abfrage über alle PrintJob-Einträge durch getrennte Datenbankabfragen für planned, printing und done. Filtere den Status jeweils in der Query, behalte das Laden von PrintJob.lines und PrintJob.files bei und wende für done die Sortierung nach completed_at mit Fallback auf created_at sowie _DONE_COLUMN_LIMIT direkt per ORDER BY und LIMIT an. Ermittle total über func.count statt aus einer unbeschränkten In-Memory-Liste.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/routes/api.py`:
- Line 283: Verschieben Sie die atomare Spulenbestandsbuchung aus dem
Erstellungsablauf des Endpoints in die Statusübergangslogik: Der neue PrintJob
soll mit planned keinen Bestand verändern, beim Übergang nach Done soll der
Bestand genau einmal reduziert werden, und nur beim Verlassen von Done
wiederhergestellt werden. Aktualisieren Sie dafür die sichtbare Job-Erstellung
mit _generate_job_code sowie die Statusverarbeitung und entfernen Sie die
sofortige Reduktion aus dem Bereich der Lines 302–310.
- Around line 20-24: Ersetzen Sie in _generate_job_code und der entsprechenden
Job-Code-Generierung in app/routes/prints.py die Verwendung von existing_count
aus COUNT durch einen persistenten, transaktionssicheren Sequenzwert. Der
Sequenzwert muss auch nach dem Löschen bestehender Jobs fortlaufend bleiben und
bei parallelen Requests unterschiedliche Werte liefern; verwenden Sie dafür den
bestehenden Sequenzmechanismus der Anwendung oder führen Sie einen solchen
zentral ein.
In `@app/routes/prints.py`:
- Around line 143-147: Ersetze in _generate_job_code die auf COUNT basierende
Sequenz durch eine kollisionssichere, monoton steigende Quelle wie
MAX(PrintJob.id) + 1, und verwende diesen Wert weiterhin als seq für
generate_code. Berücksichtige außerdem parallele Anfragen, indem du die
Codegenerierung bei einer Unique-Kollision erneut ausführst oder die bestehende
Transaktions-/Retry-Logik nutzt.
- Around line 431-439: Prüfe im Statuswechselpfad vor dem Aufruf von
_deduct_filament(job), ob der aktuelle Filamentbestand für den Abschluss
ausreicht, und lehne den Wechsel zu PrintJobStatus.done mit einer verständlichen
Fehlermeldung ab, falls nicht. Verwende dafür die vorhandene Bestands- und
Mengenlogik, ohne den Abzug selbst auf 0.0 zu begrenzen; der bestehende
Abschlusszeitpunkt soll nur bei erfolgreichem Wechsel gesetzt werden.
- Around line 168-173: Begrenze den von _detect_provider zurückgegebenen
Anbieternamen auf die maximale Länge von 50 Zeichen, insbesondere den Fallback
für unbekannte Hostnamen. Stelle sicher, dass sowohl bekannte als auch
unbekannte Providerwerte vor dem Speichern in PrintJobFile.provider diese
Spaltenlänge einhalten.
- Around line 30-35: Update the loop over spool_ids and used_g in the
form-processing handler to use strict zip semantics, so mismatched form-list
lengths raise an error instead of silently dropping entries. Preserve the
existing per-row processing and error handling for equal-length lists.
- Around line 100-105: Set the application-wide MAX_CONTENT_LENGTH configuration
to the byte equivalent of _MAX_UPLOAD_MB, so Quart rejects oversized request
bodies with 413 before await request.files fully loads them. Update the relevant
application configuration initialization while preserving the existing per-file
validation in the upload handling flow.
In `@app/routes/settings.py`:
- Around line 157-167: Aktualisiere die Code-Zuweisungsschleife für PrintJob in
zwei Schritten: Schreibe zunächst für alle betroffenen Jobs temporär eindeutige
job_code-Werte und führe danach einen Flush aus; weise anschließend die von
generate_code erzeugten Zielcodes zu. Bewahre die bestehende updated-Zählung,
indem du die ursprünglichen Codes vor der temporären Änderung lokal sicherst.
In `@app/static/js/print-viewer.js`:
- Around line 74-93: Update the fetch flow around loadedObject to use an
AbortController, pass its signal to fetch, and ensure the controller is aborted
by the viewer’s dispose() path before asynchronous loading can add objects to
the scene. Validate response.ok before reading the response body and throw a
descriptive error for non-success statuses. In the catch block, ignore
AbortError while continuing to report genuine loading failures.
In `@app/static/js/vendor/three/addons/libs/fflate.module.js`:
- Around line 1-6: Aktualisieren Sie die eingebettete fflate-Kopie in der Datei
von Version 0.8.2 auf 0.8.3 oder höher, einschließlich der zugehörigen
Implementierung von unzipSync, alternativ über einen offiziellen
Paketmanager-Import. Aktualisieren Sie außerdem den vorhandenen Header-Kommentar
mit Herkunft und neuer Version, damit die eingebettete Abhängigkeit
nachvollziehbar bleibt.
In `@app/templates/prints/index.html`:
- Around line 42-43: Escape all translated strings embedded in JavaScript
handlers with the Jinja tojson filter. Update the delete confirmation in
app/templates/prints/index.html at lines 42-43 and 84-85, the delete form in
app/templates/prints/print_form.html at lines 140-141, and the regenerate
confirmation onclick handler in app/templates/settings/index.html at lines
371-372, removing the surrounding JavaScript string quotes so each confirm call
receives the JSON-encoded translation directly.
- Around line 184-189: Update openViewer to dispose the existing activeViewer
before assigning the newly initialized viewer, ensuring repeated calls release
the previous WebGL context and geometry. Keep the current initialization flow
unchanged when no active viewer exists.
In `@app/templates/prints/print_form.html`:
- Around line 140-150: Resolve the nested form in the print form by removing the
delete `<form>` wrapper from the file-row controls while keeping the delete
button in place, assigning each button a unique `form` reference, and rendering
the corresponding `delete-file-{{ file.id }}` forms outside the main
`print-form` after it closes. Preserve the POST action, CSRF token, next value,
and confirmation behavior, using safe JSON encoding for the confirmation text.
In
`@migrations/versions/20260803_1200_aeafbed5c76f_add_print_job_files_and_status.py`:
- Around line 40-51: Remove the persistent server default for status after the
existing completed_at backfill in the migration, using the print_jobs status
column introduced by the add_column call. Keep the temporary default available
during column creation so existing rows are valid, then issue the appropriate
Alembic operation to drop it before the migration completes.
In `@migrations/versions/20260803_1600_4c0bf9e2ed81_add_print_job_code.py`:
- Line 24: Update the data migration’s job_code backfill statement to
concatenate the full decimal id without applying fixed-width LPAD padding,
ensuring large IDs remain distinct and the subsequent unique index can be
created successfully.
In `@README.md`:
- Around line 230-241: Update the feature table’s print-related entry to rename
“Print Log” to “Print Board” and describe the current board workflow, including
that filament is booked only when a job reaches Done rather than immediately.
- Around line 234-239: Update the README instructions to use the English UI
labels “New Print Job” and “Add to Board” in place of “Neuer Druckauftrag” and
“Zum Board hinzufügen”, while leaving the surrounding steps unchanged.
---
Outside diff comments:
In `@seed.py`:
- Around line 130-147: Verschiebe die Dateilöschung in clear_tables hinter await
session.commit(), sodass die Upload-Dateien erst nach erfolgreicher Löschung der
Datenbankzeilen entfernt werden. Behalte das vorherige Sammeln der
stored_filename-Werte bei und führe die bestehende Path.unlink-Logik
anschließend aus.
---
Nitpick comments:
In `@app/routes/prints.py`:
- Around line 150-165: Verschieben Sie die Konstanten _ALLOWED_FILE_EXTENSIONS,
_MAX_UPLOAD_MB, _KNOWN_PROVIDERS und _FILE_MIMETYPES im Modul an den Kopfbereich
neben _DONE_COLUMN_LIMIT, sodass sie vor den Funktionen definiert sind, die sie
verwenden; ändern Sie ihre Werte nicht.
- Around line 222-235: Ersetze die gemeinsame Abfrage über alle
PrintJob-Einträge durch getrennte Datenbankabfragen für planned, printing und
done. Filtere den Status jeweils in der Query, behalte das Laden von
PrintJob.lines und PrintJob.files bei und wende für done die Sortierung nach
completed_at mit Fallback auf created_at sowie _DONE_COLUMN_LIMIT direkt per
ORDER BY und LIMIT an. Ermittle total über func.count statt aus einer
unbeschränkten In-Memory-Liste.
In `@app/static/js/vendor/three/addons/controls/OrbitControls.js`:
- Around line 1-12: Document in the vendor area that all files under
app/static/js/vendor/three are based on three.js r169, including that the
imported Controls symbol is available in that revision. Add the note in the
established vendor documentation or an appropriate adjacent comment without
changing the import behavior.
In `@app/static/js/vendor/three/addons/loaders/3MFLoader.js`:
- Around line 1095-1126: Exclude app/static/js/vendor/** from the Biome lint
configuration so vendor code is not checked for noSwitchDeclarations. Do not
modify the switch in the 3MFLoader resource handling or the corresponding
OrbitControls.js code.
In `@app/templates/prints/index.html`:
- Around line 159-171: Update the viewer modal container with role="dialog" and
aria-modal="true"; in the existing open/close viewer flow, focus the close
button after opening and handle Escape to invoke closeViewer(). Ensure the close
button has a stable selector or identifier for focus management.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 58c3cf86-1305-495a-97b9-7ee2ef8f1ead
⛔ Files ignored due to path filters (11)
docs/screenshots/api_keys.pngis excluded by!**/*.pngdocs/screenshots/dashboard.pngis excluded by!**/*.pngdocs/screenshots/inventory_detail.pngis excluded by!**/*.pngdocs/screenshots/inventory_detail_spools.pngis excluded by!**/*.pngdocs/screenshots/inventory_list.pngis excluded by!**/*.pngdocs/screenshots/manufacturers.pngis excluded by!**/*.pngdocs/screenshots/prints_3d_viewer.pngis excluded by!**/*.pngdocs/screenshots/prints_board.pngis excluded by!**/*.pngdocs/screenshots/prints_list.pngis excluded by!**/*.pngdocs/screenshots/prints_new.pngis excluded by!**/*.pngdocs/screenshots/shop_rules.pngis excluded by!**/*.png
📒 Files selected for processing (32)
.dockerignore.gitignoreDockerfileREADME.mdapp/code_template.pyapp/config.pyapp/models/__init__.pyapp/models/print_job.pyapp/openapi.yamlapp/routes/api.pyapp/routes/inventory.pyapp/routes/prints.pyapp/routes/settings.pyapp/settings_service.pyapp/static/css/input.cssapp/static/css/tailwind.cssapp/static/js/print-viewer.jsapp/static/js/vendor/three/addons/controls/OrbitControls.jsapp/static/js/vendor/three/addons/libs/fflate.module.jsapp/static/js/vendor/three/addons/loaders/3MFLoader.jsapp/static/js/vendor/three/addons/loaders/STLLoader.jsapp/static/js/vendor/three/three.module.jsapp/templates/base.htmlapp/templates/prints/index.htmlapp/templates/prints/print_form.htmlapp/templates/settings/index.htmlapp/translations/de.yamlapp/translations/en.yamlcompose.yamlmigrations/versions/20260803_1200_aeafbed5c76f_add_print_job_files_and_status.pymigrations/versions/20260803_1600_4c0bf9e2ed81_add_print_job_code.pyseed.py
…ge job status and handle filament deduction/restoration
…or creating print jobs, deducting and restoring filament, and checking for insufficient spool weight
Summary
Turns the print log into a Print Board: a Kanban-style view (Planned → Printing → Done) instead of a flat "already printed" list.
PrintJob.status(planned/printing/done). Filament weight is now only deducted from the spool when a job is marked done — planning a print no longer touches spool inventory. Reopening a done job (ordeleting it) restores the deducted weight.
persisted via a new
app_dataDocker volume.PJ-{date}-{seq:03d}), template configurable under Settings — same pattern as spool codes, including a "regenerate all" button. Shared the template enginebetween spool codes and print codes (
app/spool_code.py→app/code_template.py) instead of duplicating the default template string across files.flat list with section labels instead.
Related issue
None
Type of change
Checklist
python migration.py revision -m "..."andpython migration.py upgrade head, migration file committedpylint apppasses (CI runs this on push/PR)_csrf_tokenhidden inputScreenshots
See updated
docs/screenshots/prints_board.png,prints_new.png,prints_3d_viewer.pngin the README.Summary by CodeRabbit
Neue Funktionen
Verbesserungen
Dokumentation